Dynomotion

Group: DynoMotion Message: 14714 From: Hardy Family Date: 5/9/2017
Subject: Use of feed hold with Move() etc.
Hi Tom,

I have some kflop code to move the axes when operating our tool changer.  It calls Move() then checks for completion in a loop using CheckDone().  Unfortunately this doesn't work nicely if the PC application sends a feed hold.  If it does, then CheckDone() returns non-zero rather than continuing to return 0 until the f/h is released and the move completes.

Am I using this correctly?  Ideally, it would be nice to accept f/h during the tool change since it gives the user a chance to load tools etc. if they notice something is wrong.  Otherwise, it would be acceptable to somehow inhibit any f/h or overrides.  As it is, interrupting any of the move segments generates an error when the code checks that the move really is complete.

Just in case it's a snafu on my part, here is the code being used:

void wait_done(unsigned axis_mask)
{
    unsigned i;
    while (axis_mask) {
        WaitNextTimeSlice();
        for (i = 0; i < 5; ++i)
            if (axis_mask & 1u<<i && CheckDone(i))
                axis_mask &= ~(1u<<i);
    }
}

int check_error()
{
    if (*supe->estop_state) {
        printf("Estop in tool change\n");
        return 1;   // estop is like a cancel
    }
    if (!chan[0].Enable || !chan[1].Enable || !chan[2].Enable) {
        printf("Axis disabled in tool change\n");
        return 2;   // usually following error
    }
    if (CS0_StoppingState) {
        printf("Stopping state %d in tool change\n", CS0_StoppingState);
        return 3;
    }
    return 0;  
}



void move_z(double z)
{
    Move(2, z);
    wait_done(1u<<2);
}


int move_z_safe()
{
    // Move to near max Z position (safest for moving to/from work, and manual changes)
    move_z(SAFE_LEVEL);
    return check_error();
}


Regards,
SJH

Group: DynoMotion Message: 14715 From: Tom Kerekes Date: 5/9/2017
Subject: Re: Use of feed hold with Move() etc.

Hi SJH,

You might try waiting for CheckDone and not Feedhold like in the code below.

Feedhold should make the Axis Done after stopping, but FeedHold will be present.  Release of Feedhold should automatically re target the Axes to the original destination.

HTH

Regards

TK


#include "KMotionDef.h"

//wait for Done and not FeedHold
int CheckDoneFH(int ch)
{
    return CheckDone(ch) && CS0_StoppingState==0;
}

main()
{
    DefineCoordSystem(0,1,2,-1);
    MoveRel(0,300000);
    while (!CheckDoneFH(0)) ;
    printf("Done\n");
    DefineCoordSystem(0,1,2,-1);
}


On 5/9/2017 7:26 PM, Hardy Family hardy.woodland.cypress@... [DynoMotion] wrote:
 
Hi Tom,

I have some kflop code to move the axes when operating our tool changer.  It calls Move() then checks for completion in a loop using CheckDone().  Unfortunately this doesn't work nicely if the PC application sends a feed hold.  If it does, then CheckDone() returns non-zero rather than continuing to return 0 until the f/h is released and the move completes.

Am I using this correctly?  Ideally, it would be nice to accept f/h during the tool change since it gives the user a chance to load tools etc. if they notice something is wrong.  Otherwise, it would be acceptable to somehow inhibit any f/h or overrides.  As it is, interrupting any of the move segments generates an error when the code checks that the move really is complete.

Just in case it's a snafu on my part, here is the code being used:

void wait_done(unsigned axis_mask)
{
    unsigned i;
    while (axis_mask) {
        WaitNextTimeSlice();
        for (i = 0; i < 5; ++i)
            if (axis_mask & 1u<<i && CheckDone(i))
                axis_mask &= ~(1u<<i);
    }
}

int check_error()
{
    if (*supe->estop_state) {
        printf("Estop in tool change\n");
        return 1;   // estop is like a cancel
    }
    if (!chan[0].Enable || !chan[1].Enable || !chan[2].Enable) {
        printf("Axis disabled in tool change\n");
        return 2;   // usually following error
    }
    if (CS0_StoppingState) {
        printf("Stopping state %d in tool change\n", CS0_StoppingState);
        return 3;
    }
    return 0;  
}



void move_z(double z)
{
    Move(2, z);
    wait_done(1u<<2);
}


int move_z_safe()
{
    // Move to near max Z position (safest for moving to/from work, and manual changes)
    move_z(SAFE_LEVEL);
    return check_error();
}


Regards,
SJH


Group: DynoMotion Message: 14716 From: Hardy Family Date: 5/9/2017
Subject: Re: Use of feed hold with Move() etc.
Thanks, that's a big improvement.  I added the check for CS0_StoppingState==0 and it works.  Unfortunately, it only works for the first feed hold.  If I press f/h a second time in the same motion command, it somehow exits the CheckDoneFH loop and yet the stopping state is 2.  Maybe there is a moment where CheckDone() is true and stopping state is 0, prior to setting the stopping state non-zero again.

Maybe I have a race condition.  This move is two axis (X,Y) so the mask is 0x3 in my wait_done() function.

Regards,
SJH


On Tue, May 9, 2017 at 7:42 PM, Tom Kerekes tk@... [DynoMotion] <DynoMotion@yahoogroups.com> wrote:
 

Hi SJH,

You might try waiting for CheckDone and not Feedhold like in the code below.

Feedhold should make the Axis Done after stopping, but FeedHold will be present.  Release of Feedhold should automatically re target the Axes to the original destination.

HTH

Regards

TK


#include "KMotionDef.h"

//wait for Done and not FeedHold
int CheckDoneFH(int ch)
{
    return CheckDone(ch) && CS0_StoppingState==0;
}

main()
{
    DefineCoordSystem(0,1,2,-1);
    MoveRel(0,300000);
    while (!CheckDoneFH(0)) ;
    printf("Done\n");
    DefineCoordSystem(0,1,2,-1);
}


On 5/9/2017 7:26 PM, Hardy Family hardy.woodland.cypress@gmail. com [DynoMotion] wrote:
 
Hi Tom,

I have some kflop code to move the axes when operating our tool changer.  It calls Move() then checks for completion in a loop using CheckDone().  Unfortunately this doesn't work nicely if the PC application sends a feed hold.  If it does, then CheckDone() returns non-zero rather than continuing to return 0 until the f/h is released and the move completes.

Am I using this correctly?  Ideally, it would be nice to accept f/h during the tool change since it gives the user a chance to load tools etc. if they notice something is wrong.  Otherwise, it would be acceptable to somehow inhibit any f/h or overrides.  As it is, interrupting any of the move segments generates an error when the code checks that the move really is complete.

Just in case it's a snafu on my part, here is the code being used:

void wait_done(unsigned axis_mask)
{
    unsigned i;
    while (axis_mask) {
        WaitNextTimeSlice();
        for (i = 0; i < 5; ++i)
            if (axis_mask & 1u<<i && CheckDone(i))
                axis_mask &= ~(1u<<i);
    }
}

int check_error()
{
    if (*supe->estop_state) {
        printf("Estop in tool change\n");
        return 1;   // estop is like a cancel
    }
    if (!chan[0].Enable || !chan[1].Enable || !chan[2].Enable) {
        printf("Axis disabled in tool change\n");
        return 2;   // usually following error
    }
    if (CS0_StoppingState) {
        printf("Stopping state %d in tool change\n", CS0_StoppingState);
        return 3;
    }
    return 0;  
}



void move_z(double z)
{
    Move(2, z);
    wait_done(1u<<2);
}


int move_z_safe()
{
    // Move to near max Z position (safest for moving to/from work, and manual changes)
    move_z(SAFE_LEVEL);
    return check_error();
}


Regards,
SJH



Group: DynoMotion Message: 14719 From: Tom Kerekes Date: 5/10/2017
Subject: Re: Use of feed hold with Move() etc.

Hi SJH,

It seems to work ok for one axis for me.  How can the routine be returning with stopping state 2 if it only returns when stopping state is 0?

Is it failing always on the 2nd feedhold?  or only sometimes?

Can you post the exact code you are running?

This seems to work for me:

#include "KMotionDef.h"

int CheckDoneFH(int ch)
{
    return CheckDone(ch) && CS0_StoppingState==0;
}

main()
{
    DefineCoordSystem(0,1,2,-1);
    MoveRel(0,300000);
    MoveRel(1,300000);
    while (!CheckDoneFH(0) && !CheckDoneFH(1)) ;
    printf("Done\n");
    DefineCoordSystem(0,1,2,-1);
}

Regards

TK


On 5/9/2017 8:24 PM, Hardy Family hardy.woodland.cypress@... [DynoMotion] wrote:
 
Thanks, that's a big improvement.  I added the check for CS0_StoppingState==0 and it works.  Unfortunately, it only works for the first feed hold.  If I press f/h a second time in the same motion command, it somehow exits the CheckDoneFH loop and yet the stopping state is 2.  Maybe there is a moment where CheckDone() is true and stopping state is 0, prior to setting the stopping state non-zero again.

Maybe I have a race condition.  This move is two axis (X,Y) so the mask is 0x3 in my wait_done() function.

Regards,
SJH


On Tue, May 9, 2017 at 7:42 PM, Tom Kerekes tk@... [DynoMotion] <DynoMotion@yahoogroups.com> wrote:
 

Hi SJH,

You might try waiting for CheckDone and not Feedhold like in the code below.

Feedhold should make the Axis Done after stopping, but FeedHold will be present.  Release of Feedhold should automatically re target the Axes to the original destination.

HTH

Regards

TK


#include "KMotionDef.h"

//wait for Done and not FeedHold
int CheckDoneFH(int ch)
{
    return CheckDone(ch) && CS0_StoppingState==0;
}

main()
{
    DefineCoordSystem(0,1,2,-1);
    MoveRel(0,300000);
    while (!CheckDoneFH(0)) ;
    printf("Done\n");
    DefineCoordSystem(0,1,2,-1);
}


On 5/9/2017 7:26 PM, Hardy Family hardy.woodland.cypress@gmail. com [DynoMotion] wrote:
 
Hi Tom,

I have some kflop code to move the axes when operating our tool changer.  It calls Move() then checks for completion in a loop using CheckDone().  Unfortunately this doesn't work nicely if the PC application sends a feed hold.  If it does, then CheckDone() returns non-zero rather than continuing to return 0 until the f/h is released and the move completes.

Am I using this correctly?  Ideally, it would be nice to accept f/h during the tool change since it gives the user a chance to load tools etc. if they notice something is wrong.  Otherwise, it would be acceptable to somehow inhibit any f/h or overrides.  As it is, interrupting any of the move segments generates an error when the code checks that the move really is complete.

Just in case it's a snafu on my part, here is the code being used:

void wait_done(unsigned axis_mask)
{
    unsigned i;
    while (axis_mask) {
        WaitNextTimeSlice();
        for (i = 0; i < 5; ++i)
            if (axis_mask & 1u<<i && CheckDone(i))
                axis_mask &= ~(1u<<i);
    }
}

int check_error()
{
    if (*supe->estop_state) {
        printf("Estop in tool change\n");
        return 1;   // estop is like a cancel
    }
    if (!chan[0].Enable || !chan[1].Enable || !chan[2].Enable) {
        printf("Axis disabled in tool change\n");
        return 2;   // usually following error
    }
    if (CS0_StoppingState) {
        printf("Stopping state %d in tool change\n", CS0_StoppingState);
        return 3;
    }
    return 0;  
}



void move_z(double z)
{
    Move(2, z);
    wait_done(1u<<2);
}


int move_z_safe()
{
    // Move to near max Z position (safest for moving to/from work, and manual changes)
    move_z(SAFE_LEVEL);
    return check_error();
}


Regards,
SJH




Group: DynoMotion Message: 14722 From: Hardy Family Date: 5/10/2017
Subject: Re: Use of feed hold with Move() etc.
Hi Tom,

Yes, it seems to always fail on the 2nd F/H.  The *exact* code is rather too complicated to post here, since our build system pulls in code from various places to build the executable for various machine configurations.  There is also a supervisor running in another thread, which shouldn't really matter, but it's possible that it is interfering somehow.

Let me research this a bit more and I'll get back to you.  One thing that might be relevant is that we are actually using the following function instead of the simple 'wait_done' in my original post.

int CheckNearlyDone(unsigned axis)
{
    TRIP_COEFF * p = chan[axis].pcoeff;
    if (CheckDoneFH(axis) || !p)
        return 1; // Fully Done
    // Look backwards thru current trip states, before current one.  If any are
    // constant velocity, we must now be decelerating, so nearly done.
    while (--p > chan[axis].c)
        if (p->a == 0. && p->b == 0.)
            return -1;  // No t^2 or t^3 coeffs, so must be constant velocity
    return 0;
}

so maybe it's this trickiness with checking for pcoeff which is making it break out of the wait prematurely.  I'm in the middle of something else at the moment, but probably need to rethink the use of StopState in the above.

Regards,
SJH


On Wed, May 10, 2017 at 10:16 AM, Tom Kerekes tk@... [DynoMotion] <DynoMotion@yahoogroups.com> wrote:
 

Hi SJH,

It seems to work ok for one axis for me.  How can the routine be returning with stopping state 2 if it only returns when stopping state is 0?

Is it failing always on the 2nd feedhold?  or only sometimes?

Can you post the exact code you are running?

This seems to work for me:

#include "KMotionDef.h"

int CheckDoneFH(int ch)
{
    return CheckDone(ch) && CS0_StoppingState==0;
}

main()
{
    DefineCoordSystem(0,1,2,-1);
    MoveRel(0,300000);
    MoveRel(1,300000);
    while (!CheckDoneFH(0) && !CheckDoneFH(1)) ;
    printf("Done\n");
    DefineCoordSystem(0,1,2,-1);
}

Regards

TK


On 5/9/2017 8:24 PM, Hardy Family hardy.woodland.cypress@gmail. com [DynoMotion] wrote:
 
Thanks, that's a big improvement.  I added the check for CS0_StoppingState==0 and it works.  Unfortunately, it only works for the first feed hold.  If I press f/h a second time in the same motion command, it somehow exits the CheckDoneFH loop and yet the stopping state is 2.  Maybe there is a moment where CheckDone() is true and stopping state is 0, prior to setting the stopping state non-zero again.

Maybe I have a race condition.  This move is two axis (X,Y) so the mask is 0x3 in my wait_done() function.

Regards,
SJH


On Tue, May 9, 2017 at 7:42 PM, Tom Kerekes tk@... [DynoMotion] <DynoMotion@yahoogroups.com> wrote:
 

Hi SJH,

You might try waiting for CheckDone and not Feedhold like in the code below.

Feedhold should make the Axis Done after stopping, but FeedHold will be present.  Release of Feedhold should automatically re target the Axes to the original destination.

HTH

Regards

TK


#include "KMotionDef.h"

//wait for Done and not FeedHold
int CheckDoneFH(int ch)
{
    return CheckDone(ch) && CS0_StoppingState==0;
}

main()
{
    DefineCoordSystem(0,1,2,-1);
    MoveRel(0,300000);
    while (!CheckDoneFH(0)) ;
    printf("Done\n");
    DefineCoordSystem(0,1,2,-1);
}


On 5/9/2017 7:26 PM, Hardy Family hardy.woodland.cypress@gmail.c om [DynoMotion] wrote:
 
Hi Tom,

I have some kflop code to move the axes when operating our tool changer.  It calls Move() then checks for completion in a loop using CheckDone().  Unfortunately this doesn't work nicely if the PC application sends a feed hold.  If it does, then CheckDone() returns non-zero rather than continuing to return 0 until the f/h is released and the move completes.

Am I using this correctly?  Ideally, it would be nice to accept f/h during the tool change since it gives the user a chance to load tools etc. if they notice something is wrong.  Otherwise, it would be acceptable to somehow inhibit any f/h or overrides.  As it is, interrupting any of the move segments generates an error when the code checks that the move really is complete.

Just in case it's a snafu on my part, here is the code being used:

void wait_done(unsigned axis_mask)
{
    unsigned i;
    while (axis_mask) {
        WaitNextTimeSlice();
        for (i = 0; i < 5; ++i)
            if (axis_mask & 1u<<i && CheckDone(i))
                axis_mask &= ~(1u<<i);
    }
}

int check_error()
{
    if (*supe->estop_state) {
        printf("Estop in tool change\n");
        return 1;   // estop is like a cancel
    }
    if (!chan[0].Enable || !chan[1].Enable || !chan[2].Enable) {
        printf("Axis disabled in tool change\n");
        return 2;   // usually following error
    }
    if (CS0_StoppingState) {
        printf("Stopping state %d in tool change\n", CS0_StoppingState);
        return 3;
    }
    return 0;  
}



void move_z(double z)
{
    Move(2, z);
    wait_done(1u<<2);
}


int move_z_safe()
{
    // Move to near max Z position (safest for moving to/from work, and manual changes)
    move_z(SAFE_LEVEL);
    return check_error();
}


Regards,
SJH





Group: DynoMotion Message: 14740 From: Hardy Family Date: 5/12/2017
Subject: Re: Use of feed hold with Move() etc.
It seems like sending a "StopImmediate 1" command from the PC, to resume from a feed hold, is first setting CS0_StoppingState back to zero, but for at least a short time thereafter, CheckDone() returns 1.  This causes it to break out of the wait loop.

This is the code I am using to debug the wait:

void wait_done_dbg(unsigned axis_mask)
{
    unsigned i;
    unsigned moving = axis_mask;
    unsigned iam = axis_mask;
    int css = CS0_StoppingState;
    double lmdx = ch0->LastMotionDest;
    double lmdy = ch1->LastMotionDest;
    double lmdz = ch2->LastMotionDest;
    int ess = *supe->estop_state;
    int enab = chan[0].Enable | chan[1].Enable<<1 | chan[2].Enable<<2;
    int e;
   
    printf("WD: Entry: mask=%X, lmd=[%.0f,%.0f,%.0f], ss=%d\n", iam, lmdx, lmdy, lmdz, ess);
    while (axis_mask) {
        WaitNextTimeSlice();
        for (i = 0; i < 5; ++i)
            if (axis_mask & 1u<<i && CheckDoneFH(i))
                axis_mask &= ~(1u<<i);
        if (axis_mask != iam) {
            printf("WD: axis_mask now %X\n", axis_mask);
            iam = axis_mask;
        }
        if (CS0_StoppingState != css) {
            printf("WD: stop state now %d\n", CS0_StoppingState);
            css = CS0_StoppingState;
        }
        if (ch0->LastMotionDest != lmdx) {
            printf("WD: lmd[x] now %.0f\n", ch0->LastMotionDest);
            lmdx = ch0->LastMotionDest;
        }
        if (ch1->LastMotionDest != lmdy) {
            printf("WD: lmd[y] now %.0f\n", ch1->LastMotionDest);
            lmdy = ch1->LastMotionDest;
        }
        if (ch2->LastMotionDest != lmdz) {
            printf("WD: lmd[z] now %.0f\n", ch2->LastMotionDest);
            lmdz = ch2->LastMotionDest;
        }
        if (*supe->estop_state != ess) {
            printf("WD: Estop state now %d\n", *supe->estop_state);
            ess = *supe->estop_state;
        }
        e = chan[0].Enable | chan[1].Enable<<1 | chan[2].Enable<<2;
        if (e != enab) {
            printf("WD: Axis enable mask now %X\n", e);
            enab = e;
        }
    }
    printf("WD: Exit: pos=[%.0f,%.0f,%.0f]\n", ch0->Position, ch1->Position, ch2->Position);
    if (moving & 1 && fast_fabs(lmdx-ch0->Position) > 100. ||
        moving & 2 && fast_fabs(lmdy-ch1->Position) > 100. ||
        moving & 4 && fast_fabs(lmdz-ch2->Position) > 100.)
        printf("!!!! which ain't even close!\n");
}


and the console log gets the following for an XY move:

+     0 k: WD: Entry: mask=3, lmd=[16500,-94367,11980], ss=0
+     0 k: WD: axis_mask now 1
+   643 k: WD: stop state now 2
+   189 k: WD: stop state now 4
+  1804 k: WD: axis_mask now 0
+     0 k: WD: stop state now 0
+     0 k: WD: Exit: pos=[-56063,-94366,11980]
+     0 k: !!!! which ain't even close!



(I add the '+ n k:' prefix to print the number of ms since last log print, as seen by the PC.)

On the 3rd line, I press feed hold (StopImmediate 0) and the stopping state ends up at 4 with the axis halted.  Then at line 5 I release the f/h, and it sees axis_mask==0, which is because CheckDone() returned 1, and at the same time stop state is back to 0.  As the next line shows, it didn't end up at the destination.

So either the kflop forgot to set CheckDone() to return zero when f/h released but move was not complete, or maybe it takes a few ticks to set it properly.

Is there anything else you'd like me to try?

BTW, we are still using firmware 433q.

Regards,
SJH



On Wed, May 10, 2017 at 12:31 PM, Hardy Family <hardy.woodland.cypress@...> wrote:
Hi Tom,

Yes, it seems to always fail on the 2nd F/H.  The *exact* code is rather too complicated to post here, since our build system pulls in code from various places to build the executable for various machine configurations.  There is also a supervisor running in another thread, which shouldn't really matter, but it's possible that it is interfering somehow.

Let me research this a bit more and I'll get back to you.  One thing that might be relevant is that we are actually using the following function instead of the simple 'wait_done' in my original post.

int CheckNearlyDone(unsigned axis)
{
    TRIP_COEFF * p = chan[axis].pcoeff;
    if (CheckDoneFH(axis) || !p)
        return 1; // Fully Done
    // Look backwards thru current trip states, before current one.  If any are
    // constant velocity, we must now be decelerating, so nearly done.
    while (--p > chan[axis].c)
        if (p->a == 0. && p->b == 0.)
            return -1;  // No t^2 or t^3 coeffs, so must be constant velocity
    return 0;
}

so maybe it's this trickiness with checking for pcoeff which is making it break out of the wait prematurely.  I'm in the middle of something else at the moment, but probably need to rethink the use of StopState in the above.

Regards,
SJH


On Wed, May 10, 2017 at 10:16 AM, Tom Kerekes tk@... [DynoMotion] <DynoMotion@yahoogroups.com> wrote:
 

Hi SJH,

It seems to work ok for one axis for me.  How can the routine be returning with stopping state 2 if it only returns when stopping state is 0?

Is it failing always on the 2nd feedhold?  or only sometimes?

Can you post the exact code you are running?

This seems to work for me:

#include "KMotionDef.h"

int CheckDoneFH(int ch)
{
    return CheckDone(ch) && CS0_StoppingState==0;
}

main()
{
    DefineCoordSystem(0,1,2,-1);
    MoveRel(0,300000);
    MoveRel(1,300000);
    while (!CheckDoneFH(0) && !CheckDoneFH(1)) ;
    printf("Done\n");
    DefineCoordSystem(0,1,2,-1);
}

Regards

TK


On 5/9/2017 8:24 PM, Hardy Family hardy.woodland.cypress@gmail.c om [DynoMotion] wrote:
 
Thanks, that's a big improvement.  I added the check for CS0_StoppingState==0 and it works.  Unfortunately, it only works for the first feed hold.  If I press f/h a second time in the same motion command, it somehow exits the CheckDoneFH loop and yet the stopping state is 2.  Maybe there is a moment where CheckDone() is true and stopping state is 0, prior to setting the stopping state non-zero again.

Maybe I have a race condition.  This move is two axis (X,Y) so the mask is 0x3 in my wait_done() function.

Regards,
SJH


On Tue, May 9, 2017 at 7:42 PM, Tom Kerekes tk@... [DynoMotion] <DynoMotion@yahoogroups.com> wrote:
 

Hi SJH,

You might try waiting for CheckDone and not Feedhold like in the code below.

Feedhold should make the Axis Done after stopping, but FeedHold will be present.  Release of Feedhold should automatically re target the Axes to the original destination.

HTH

Regards

TK


#include "KMotionDef.h"

//wait for Done and not FeedHold
int CheckDoneFH(int ch)
{
    return CheckDone(ch) && CS0_StoppingState==0;
}

main()
{
    DefineCoordSystem(0,1,2,-1);
    MoveRel(0,300000);
    while (!CheckDoneFH(0)) ;
    printf("Done\n");
    DefineCoordSystem(0,1,2,-1);
}


On 5/9/2017 7:26 PM, Hardy Family hardy.woodland.cypress@gmail.c om [DynoMotion] wrote:
 
Hi Tom,

I have some kflop code to move the axes when operating our tool changer.  It calls Move() then checks for completion in a loop using CheckDone().  Unfortunately this doesn't work nicely if the PC application sends a feed hold.  If it does, then CheckDone() returns non-zero rather than continuing to return 0 until the f/h is released and the move completes.

Am I using this correctly?  Ideally, it would be nice to accept f/h during the tool change since it gives the user a chance to load tools etc. if they notice something is wrong.  Otherwise, it would be acceptable to somehow inhibit any f/h or overrides.  As it is, interrupting any of the move segments generates an error when the code checks that the move really is complete.

Just in case it's a snafu on my part, here is the code being used:

void wait_done(unsigned axis_mask)
{
    unsigned i;
    while (axis_mask) {
        WaitNextTimeSlice();
        for (i = 0; i < 5; ++i)
            if (axis_mask & 1u<<i && CheckDone(i))
                axis_mask &= ~(1u<<i);
    }
}

int check_error()
{
    if (*supe->estop_state) {
        printf("Estop in tool change\n");
        return 1;   // estop is like a cancel
    }
    if (!chan[0].Enable || !chan[1].Enable || !chan[2].Enable) {
        printf("Axis disabled in tool change\n");
        return 2;   // usually following error
    }
    if (CS0_StoppingState) {
        printf("Stopping state %d in tool change\n", CS0_StoppingState);
        return 3;
    }
    return 0;  
}



void move_z(double z)
{
    Move(2, z);
    wait_done(1u<<2);
}


int move_z_safe()
{
    // Move to near max Z position (safest for moving to/from work, and manual changes)
    move_z(SAFE_LEVEL);
    return check_error();
}


Regards,
SJH






Group: DynoMotion Message: 14742 From: Hardy Family Date: 5/12/2017
Subject: Re: Use of feed hold with Move() etc.
I tried adding a few WaitNextTimeSlice() calls then do another CheckDone(), and it works!

So it looks like I need to be sure, to be sure.

Regards,
SJH


On Fri, May 12, 2017 at 4:21 PM, Hardy Family <hardy.woodland.cypress@...> wrote:
It seems like sending a "StopImmediate 1" command from the PC, to resume from a feed hold, is first setting CS0_StoppingState back to zero, but for at least a short time thereafter, CheckDone() returns 1.  This causes it to break out of the wait loop.

This is the code I am using to debug the wait:

void wait_done_dbg(unsigned axis_mask)
{
    unsigned i;
    unsigned moving = axis_mask;
    unsigned iam = axis_mask;
    int css = CS0_StoppingState;
    double lmdx = ch0->LastMotionDest;
    double lmdy = ch1->LastMotionDest;
    double lmdz = ch2->LastMotionDest;
    int ess = *supe->estop_state;
    int enab = chan[0].Enable | chan[1].Enable<<1 | chan[2].Enable<<2;
    int e;
   
    printf("WD: Entry: mask=%X, lmd=[%.0f,%.0f,%.0f], ss=%d\n", iam, lmdx, lmdy, lmdz, ess);
    while (axis_mask) {
        WaitNextTimeSlice();
        for (i = 0; i < 5; ++i)
            if (axis_mask & 1u<<i && CheckDoneFH(i))
                axis_mask &= ~(1u<<i);
        if (axis_mask != iam) {
            printf("WD: axis_mask now %X\n", axis_mask);
            iam = axis_mask;
        }
        if (CS0_StoppingState != css) {
            printf("WD: stop state now %d\n", CS0_StoppingState);
            css = CS0_StoppingState;
        }
        if (ch0->LastMotionDest != lmdx) {
            printf("WD: lmd[x] now %.0f\n", ch0->LastMotionDest);
            lmdx = ch0->LastMotionDest;
        }
        if (ch1->LastMotionDest != lmdy) {
            printf("WD: lmd[y] now %.0f\n", ch1->LastMotionDest);
            lmdy = ch1->LastMotionDest;
        }
        if (ch2->LastMotionDest != lmdz) {
            printf("WD: lmd[z] now %.0f\n", ch2->LastMotionDest);
            lmdz = ch2->LastMotionDest;
        }
        if (*supe->estop_state != ess) {
            printf("WD: Estop state now %d\n", *supe->estop_state);
            ess = *supe->estop_state;
        }
        e = chan[0].Enable | chan[1].Enable<<1 | chan[2].Enable<<2;
        if (e != enab) {
            printf("WD: Axis enable mask now %X\n", e);
            enab = e;
        }
    }
    printf("WD: Exit: pos=[%.0f,%.0f,%.0f]\n", ch0->Position, ch1->Position, ch2->Position);
    if (moving & 1 && fast_fabs(lmdx-ch0->Position) > 100. ||
        moving & 2 && fast_fabs(lmdy-ch1->Position) > 100. ||
        moving & 4 && fast_fabs(lmdz-ch2->Position) > 100.)
        printf("!!!! which ain't even close!\n");
}


and the console log gets the following for an XY move:

+     0 k: WD: Entry: mask=3, lmd=[16500,-94367,11980], ss=0
+     0 k: WD: axis_mask now 1
+   643 k: WD: stop state now 2
+   189 k: WD: stop state now 4
+  1804 k: WD: axis_mask now 0
+     0 k: WD: stop state now 0
+     0 k: WD: Exit: pos=[-56063,-94366,11980]
+     0 k: !!!! which ain't even close!



(I add the '+ n k:' prefix to print the number of ms since last log print, as seen by the PC.)

On the 3rd line, I press feed hold (StopImmediate 0) and the stopping state ends up at 4 with the axis halted.  Then at line 5 I release the f/h, and it sees axis_mask==0, which is because CheckDone() returned 1, and at the same time stop state is back to 0.  As the next line shows, it didn't end up at the destination.

So either the kflop forgot to set CheckDone() to return zero when f/h released but move was not complete, or maybe it takes a few ticks to set it properly.

Is there anything else you'd like me to try?

BTW, we are still using firmware 433q.

Regards,
SJH



On Wed, May 10, 2017 at 12:31 PM, Hardy Family <hardy.woodland.cypress@gmail. com> wrote:
Hi Tom,

Yes, it seems to always fail on the 2nd F/H.  The *exact* code is rather too complicated to post here, since our build system pulls in code from various places to build the executable for various machine configurations.  There is also a supervisor running in another thread, which shouldn't really matter, but it's possible that it is interfering somehow.

Let me research this a bit more and I'll get back to you.  One thing that might be relevant is that we are actually using the following function instead of the simple 'wait_done' in my original post.

int CheckNearlyDone(unsigned axis)
{
    TRIP_COEFF * p = chan[axis].pcoeff;
    if (CheckDoneFH(axis) || !p)
        return 1; // Fully Done
    // Look backwards thru current trip states, before current one.  If any are
    // constant velocity, we must now be decelerating, so nearly done.
    while (--p > chan[axis].c)
        if (p->a == 0. && p->b == 0.)
            return -1;  // No t^2 or t^3 coeffs, so must be constant velocity
    return 0;
}

so maybe it's this trickiness with checking for pcoeff which is making it break out of the wait prematurely.  I'm in the middle of something else at the moment, but probably need to rethink the use of StopState in the above.

Regards,
SJH


On Wed, May 10, 2017 at 10:16 AM, Tom Kerekes tk@... [DynoMotion] <DynoMotion@yahoogroups.com> wrote:
 

Hi SJH,

It seems to work ok for one axis for me.  How can the routine be returning with stopping state 2 if it only returns when stopping state is 0?

Is it failing always on the 2nd feedhold?  or only sometimes?

Can you post the exact code you are running?

This seems to work for me:

#include "KMotionDef.h"

int CheckDoneFH(int ch)
{
    return CheckDone(ch) && CS0_StoppingState==0;
}

main()
{
    DefineCoordSystem(0,1,2,-1);
    MoveRel(0,300000);
    MoveRel(1,300000);
    while (!CheckDoneFH(0) && !CheckDoneFH(1)) ;
    printf("Done\n");
    DefineCoordSystem(0,1,2,-1);
}

Regards

TK


On 5/9/2017 8:24 PM, Hardy Family hardy.woodland.cypress@gmail.c om [DynoMotion] wrote:
 
Thanks, that's a big improvement.  I added the check for CS0_StoppingState==0 and it works.  Unfortunately, it only works for the first feed hold.  If I press f/h a second time in the same motion command, it somehow exits the CheckDoneFH loop and yet the stopping state is 2.  Maybe there is a moment where CheckDone() is true and stopping state is 0, prior to setting the stopping state non-zero again.

Maybe I have a race condition.  This move is two axis (X,Y) so the mask is 0x3 in my wait_done() function.

Regards,
SJH


On Tue, May 9, 2017 at 7:42 PM, Tom Kerekes tk@... [DynoMotion] <DynoMotion@yahoogroups.com> wrote:
 

Hi SJH,

You might try waiting for CheckDone and not Feedhold like in the code below.

Feedhold should make the Axis Done after stopping, but FeedHold will be present.  Release of Feedhold should automatically re target the Axes to the original destination.

HTH

Regards

TK


#include "KMotionDef.h"

//wait for Done and not FeedHold
int CheckDoneFH(int ch)
{
    return CheckDone(ch) && CS0_StoppingState==0;
}

main()
{
    DefineCoordSystem(0,1,2,-1);
    MoveRel(0,300000);
    while (!CheckDoneFH(0)) ;
    printf("Done\n");
    DefineCoordSystem(0,1,2,-1);
}


On 5/9/2017 7:26 PM, Hardy Family hardy.woodland.cypress@gmail.c om [DynoMotion] wrote:
 
Hi Tom,

I have some kflop code to move the axes when operating our tool changer.  It calls Move() then checks for completion in a loop using CheckDone().  Unfortunately this doesn't work nicely if the PC application sends a feed hold.  If it does, then CheckDone() returns non-zero rather than continuing to return 0 until the f/h is released and the move completes.

Am I using this correctly?  Ideally, it would be nice to accept f/h during the tool change since it gives the user a chance to load tools etc. if they notice something is wrong.  Otherwise, it would be acceptable to somehow inhibit any f/h or overrides.  As it is, interrupting any of the move segments generates an error when the code checks that the move really is complete.

Just in case it's a snafu on my part, here is the code being used:

void wait_done(unsigned axis_mask)
{
    unsigned i;
    while (axis_mask) {
        WaitNextTimeSlice();
        for (i = 0; i < 5; ++i)
            if (axis_mask & 1u<<i && CheckDone(i))
                axis_mask &= ~(1u<<i);
    }
}

int check_error()
{
    if (*supe->estop_state) {
        printf("Estop in tool change\n");
        return 1;   // estop is like a cancel
    }
    if (!chan[0].Enable || !chan[1].Enable || !chan[2].Enable) {
        printf("Axis disabled in tool change\n");
        return 2;   // usually following error
    }
    if (CS0_StoppingState) {
        printf("Stopping state %d in tool change\n", CS0_StoppingState);
        return 3;
    }
    return 0;  
}



void move_z(double z)
{
    Move(2, z);
    wait_done(1u<<2);
}


int move_z_safe()
{
    // Move to near max Z position (safest for moving to/from work, and manual changes)
    move_z(SAFE_LEVEL);
    return check_error();
}


Regards,
SJH







Group: DynoMotion Message: 14746 From: TKSOFT Date: 5/13/2017
Subject: Re: Use of feed hold with Move() etc.
Hi SJH,

I see now there is a flaw where KFLOP on Resume clears CS0_StoppingState
and then immediately commands the motions. So there would be a small
window of time between feedhold clear and no motion. It isn't clear why
my test code doesn't show the issue. But that is the nature of such
issues. Calculating the new Trajectory does involve quite a bit of
calculation and can vary depending on circumstances. I don't see an
elegant solution. I'm still thinking the best solution it to wait for
the destination to be at the target position.

Regards
TK

On 2017-05-12 17:36, Hardy Family hardy.woodland.cypress@...
[DynoMotion] wrote:
> I tried adding a few WaitNextTimeSlice() calls then do another
> CheckDone(), and it works!
>
> So it looks like I need to be sure, to be sure.
>
> Regards,
> SJH
>
> On Fri, May 12, 2017 at 4:21 PM, Hardy Family
> <hardy.woodland.cypress@...> wrote:
>
>> It seems like sending a "StopImmediate 1" command from the PC, to
>> resume from a feed hold, is first setting CS0_StoppingState back to
>> zero, but for at least a short time thereafter, CheckDone() returns
>> 1. This causes it to break out of the wait loop.
>>
>> This is the code I am using to debug the wait:
>>
>> void wait_done_dbg(unsigned axis_mask)
>> {
>> unsigned i;
>> unsigned moving = axis_mask;
>> unsigned iam = axis_mask;
>> int css = CS0_StoppingState;
>> double lmdx = ch0->LastMotionDest;
>> double lmdy = ch1->LastMotionDest;
>> double lmdz = ch2->LastMotionDest;
>> int ess = *supe->estop_state;
>> int enab = chan[0].Enable | chan[1].Enable<<1 |
>> chan[2].Enable<<2;
>> int e;
>>
>> printf("WD: Entry: mask=%X, lmd=[%.0f,%.0f,%.0f], ss=%d\n", iam,
>> lmdx, lmdy, lmdz, ess);
>> while (axis_mask) {
>> WaitNextTimeSlice();
>> for (i = 0; i < 5; ++i)
>> if (axis_mask & 1u<<i && CheckDoneFH(i))
>> axis_mask &= ~(1u<<i);
>> if (axis_mask != iam) {
>> printf("WD: axis_mask now %X\n", axis_mask);
>> iam = axis_mask;
>> }
>> if (CS0_StoppingState != css) {
>> printf("WD: stop state now %d\n", CS0_StoppingState);
>> css = CS0_StoppingState;
>> }
>> if (ch0->LastMotionDest != lmdx) {
>> printf("WD: lmd[x] now %.0f\n", ch0->LastMotionDest);
>> lmdx = ch0->LastMotionDest;
>> }
>> if (ch1->LastMotionDest != lmdy) {
>> printf("WD: lmd[y] now %.0f\n", ch1->LastMotionDest);
>> lmdy = ch1->LastMotionDest;
>> }
>> if (ch2->LastMotionDest != lmdz) {
>> printf("WD: lmd[z] now %.0f\n", ch2->LastMotionDest);
>> lmdz = ch2->LastMotionDest;
>> }
>> if (*supe->estop_state != ess) {
>> printf("WD: Estop state now %d\n", *supe->estop_state);
>> ess = *supe->estop_state;
>> }
>> e = chan[0].Enable | chan[1].Enable<<1 | chan[2].Enable<<2;
>> if (e != enab) {
>> printf("WD: Axis enable mask now %X\n", e);
>> enab = e;
>> }
>> }
>> printf("WD: Exit: pos=[%.0f,%.0f,%.0f]\n", ch0->Position,
>> ch1->Position, ch2->Position);
>> if (moving & 1 && fast_fabs(lmdx-ch0->Position) > 100. ||
>> moving & 2 && fast_fabs(lmdy-ch1->Position) > 100. ||
>> moving & 4 && fast_fabs(lmdz-ch2->Position) > 100.)
>> printf("!!!! which ain't even close!\n");
>> }
>>
>> and the console log gets the following for an XY move:
>>
>> + 0 k: WD: Entry: mask=3, lmd=[16500,-94367,11980], ss=0
>> + 0 k: WD: axis_mask now 1
>> + 643 k: WD: stop state now 2
>> + 189 k: WD: stop state now 4
>> + 1804 k: WD: axis_mask now 0
>> + 0 k: WD: stop state now 0
>> + 0 k: WD: Exit: pos=[-56063,-94366,11980]
>> + 0 k: !!!! which ain't even close!
>>
>> (I add the '+ n k:' prefix to print the number of ms since last log
>> print, as seen by the PC.)
>>
>> On the 3rd line, I press feed hold (StopImmediate 0) and the
>> stopping state ends up at 4 with the axis halted. Then at line 5 I
>> release the f/h, and it sees axis_mask==0, which is because
>> CheckDone() returned 1, and at the same time stop state is back to
>> 0. As the next line shows, it didn't end up at the destination.
>>
>> So either the kflop forgot to set CheckDone() to return zero when
>> f/h released but move was not complete, or maybe it takes a few
>> ticks to set it properly.
>>
>> Is there anything else you'd like me to try?
>>
>> BTW, we are still using firmware 433q.
>>
>> Regards,
>> SJH
>>
>> On Wed, May 10, 2017 at 12:31 PM, Hardy Family
>> <hardy.woodland.cypress@...> wrote:
>>
>> Hi Tom,
>>
>> Yes, it seems to always fail on the 2nd F/H. The *exact* code is
>> rather too complicated to post here, since our build system pulls in
>> code from various places to build the executable for various machine
>> configurations. There is also a supervisor running in another
>> thread, which shouldn't really matter, but it's possible that it is
>> interfering somehow.
>>
>> Let me research this a bit more and I'll get back to you. One thing
>> that might be relevant is that we are actually using the following
>> function instead of the simple 'wait_done' in my original post.
>>
>> int CheckNearlyDone(unsigned axis)
>> {
>> TRIP_COEFF * p = chan[axis].pcoeff;
>> if (CheckDoneFH(axis) || !p)
>> return 1; // Fully Done
>> // Look backwards thru current trip states, before current one.
>> If any are
>> // constant velocity, we must now be decelerating, so nearly
>> done.
>> while (--p > chan[axis].c)
>> if (p->a == 0. && p->b == 0.)
>> return -1; // No t^2 or t^3 coeffs, so must be constant
>> velocity
>> return 0;
>> }
>>
>> so maybe it's this trickiness with checking for pcoeff which is
>> making it break out of the wait prematurely. I'm in the middle of
>> something else at the moment, but probably need to rethink the use
>> of StopState in the above.
>>
>> Regards,
>> SJH
>>
>> On Wed, May 10, 2017 at 10:16 AM, Tom Kerekes tk@...
>> [DynoMotion] <DynoMotion@yahoogroups.com> wrote:
>>
>> Hi SJH,
>>
>> It seems to work ok for one axis for me. How can the routine be
>> returning with stopping state 2 if it only returns when stopping
>> state is 0?
>>
>> Is it failing always on the 2nd feedhold? or only sometimes?
>>
>> Can you post the exact code you are running?
>>
>> This seems to work for me:
>>
>> #include "KMotionDef.h"
>>
>> int CheckDoneFH(int ch)
>> {
>> return CheckDone(ch) && CS0_StoppingState==0;
>> }
>>
>> main()
>> {
>> DefineCoordSystem(0,1,2,-1);
>> MoveRel(0,300000);
>> MoveRel(1,300000);
>> while (!CheckDoneFH(0) && !CheckDoneFH(1)) ;
>> printf("Done\n");
>> DefineCoordSystem(0,1,2,-1);
>> }
>>
>> Regards
>>
>> TK
>>
>> On 5/9/2017 8:24 PM, Hardy Family hardy.woodland.cypress@...
>> [DynoMotion] wrote:
>>
>> Thanks, that's a big improvement. I added the check for
>> CS0_StoppingState==0 and it works. Unfortunately, it only works for
>> the first feed hold. If I press f/h a second time in the same
>> motion command, it somehow exits the CheckDoneFH loop and yet the
>> stopping state is 2. Maybe there is a moment where CheckDone() is
>> true and stopping state is 0, prior to setting the stopping state
>> non-zero again.
>>
>> Maybe I have a race condition. This move is two axis (X,Y) so the
>> mask is 0x3 in my wait_done() function.
>>
>> Regards,
>> SJH
>>
>> On Tue, May 9, 2017 at 7:42 PM, Tom Kerekes tk@...
>> [DynoMotion] <DynoMotion@yahoogroups.com> wrote:
>>
>> Hi SJH,
>>
>> You might try waiting for CheckDone and not Feedhold like in the
>> code below.
>>
>> Feedhold should make the Axis Done after stopping, but FeedHold will
>> be present. Release of Feedhold should automatically re target the
>> Axes to the original destination.
>>
>> HTH
>>
>> Regards
>>
>> TK
>>
>> #include "KMotionDef.h"
>>
>> //wait for Done and not FeedHold
>> int CheckDoneFH(int ch)
>> {
>> return CheckDone(ch) && CS0_StoppingState==0;
>> }
>>
>> main()
>> {
>> DefineCoordSystem(0,1,2,-1);
>> MoveRel(0,300000);
>> while (!CheckDoneFH(0)) ;
>> printf("Done\n");
>> DefineCoordSystem(0,1,2,-1);
>> }
>>
>> On 5/9/2017 7:26 PM, Hardy Family hardy.woodland.cypress@...
>> [DynoMotion] wrote:
>>
>> Hi Tom,
>>
>> I have some kflop code to move the axes when operating our tool
>> changer. It calls Move() then checks for completion in a loop using
>> CheckDone(). Unfortunately this doesn't work nicely if the PC
>> application sends a feed hold. If it does, then CheckDone() returns
>> non-zero rather than continuing to return 0 until the f/h is
>> released and the move completes.
>>
>> Am I using this correctly? Ideally, it would be nice to accept f/h
>> during the tool change since it gives the user a chance to load
>> tools etc. if they notice something is wrong. Otherwise, it would
>> be acceptable to somehow inhibit any f/h or overrides. As it is,
>> interrupting any of the move segments generates an error when the
>> code checks that the move really is complete.
>>
>> Just in case it's a snafu on my part, here is the code being used:
>>
>> void wait_done(unsigned axis_mask)
>> {
>> unsigned i;
>> while (axis_mask) {
>> WaitNextTimeSlice();
>> for (i = 0; i < 5; ++i)
>> if (axis_mask & 1u<<i && CheckDone(i))
>> axis_mask &= ~(1u<<i);
>> }
>> }
>>
>> int check_error()
>> {
>> if (*supe->estop_state) {
>> printf("Estop in tool change\n");
>> return 1; // estop is like a cancel
>> }
>> if (!chan[0].Enable || !chan[1].Enable || !chan[2].Enable) {
>> printf("Axis disabled in tool change\n");
>> return 2; // usually following error
>> }
>> if (CS0_StoppingState) {
>> printf("Stopping state %d in tool change\n",
>> CS0_StoppingState);
>> return 3;
>> }
>> return 0;
>> }
>>
>> void move_z(double z)
>> {
>> Move(2, z);
>> wait_done(1u<<2);
>> }
>>
>> int move_z_safe()
>> {
>> // Move to near max Z position (safest for moving to/from work,
>> and manual changes)
>> move_z(SAFE_LEVEL);
>> return check_error();
>> }
>>
>> Regards,
>> SJH
>
>
>
> Links:
> ------
> [1]
> https://groups.yahoo.com/neo/groups/DynoMotion/conversations/messages/14742;_ylc=X3oDMTJyYjlwNHM0BF9TAzk3MzU5NzE0BGdycElkAzE1ODU4MDAxBGdycHNwSWQDMTcwNjU1NDIwNQRtc2dJZAMxNDc0MgRzZWMDZnRyBHNsawNycGx5BHN0aW1lAzE0OTQ2MzU3OTc-?act=reply&messageNum=14742
> [2]
> https://groups.yahoo.com/neo/groups/DynoMotion/conversations/newtopic;_ylc=X3oDMTJmdGRucWhrBF9TAzk3MzU5NzE0BGdycElkAzE1ODU4MDAxBGdycHNwSWQDMTcwNjU1NDIwNQRzZWMDZnRyBHNsawNudHBjBHN0aW1lAzE0OTQ2MzU3OTc-
> [3]
> https://groups.yahoo.com/neo/groups/DynoMotion/conversations/topics/14714;_ylc=X3oDMTM3aGZqbTlvBF9TAzk3MzU5NzE0BGdycElkAzE1ODU4MDAxBGdycHNwSWQDMTcwNjU1NDIwNQRtc2dJZAMxNDc0MgRzZWMDZnRyBHNsawN2dHBjBHN0aW1lAzE0OTQ2MzU3OTcEdHBjSWQDMTQ3MTQ-
> [4] https://yho.com/1wwmgg
> [5]
> https://groups.yahoo.com/neo/groups/DynoMotion/info;_ylc=X3oDMTJmY3RlaWs0BF9TAzk3MzU5NzE0BGdycElkAzE1ODU4MDAxBGdycHNwSWQDMTcwNjU1NDIwNQRzZWMDdnRsBHNsawN2Z2hwBHN0aW1lAzE0OTQ2MzU3OTc-
> [6]
> https://groups.yahoo.com/neo/groups/DynoMotion/members/all;_ylc=X3oDMTJnZzQxaGRuBF9TAzk3MzU5NzE0BGdycElkAzE1ODU4MDAxBGdycHNwSWQDMTcwNjU1NDIwNQRzZWMDdnRsBHNsawN2bWJycwRzdGltZQMxNDk0NjM1Nzk3
> [7]
> https://groups.yahoo.com/neo;_ylc=X3oDMTJldjNncnQ2BF9TAzk3NDc2NTkwBGdycElkAzE1ODU4MDAxBGdycHNwSWQDMTcwNjU1NDIwNQRzZWMDZnRyBHNsawNnZnAEc3RpbWUDMTQ5NDYzNTc5Nw--
> [8] https://info.yahoo.com/privacy/us/yahoo/groups/details.html
> [9] https://info.yahoo.com/legal/us/yahoo/utos/terms/
Group: DynoMotion Message: 14747 From: Hardy Family Date: 5/13/2017
Subject: Re: Use of feed hold with Move() etc.
I can certainly add the distance-to-go check.  Is the ch0->LastMotionDest field a reliable indicator of the ultimate destination?  If possible, I would like to avoid having to pass the ending coordinates as a parameter to my wait() function, so this would be useful.

Since our tool changer, probing, etc. routines can make a lot of these type of moves, it is a considerable improvement to be able to wait until "nearly there" instead of a complete stop.  The algorithm I coded before (mentioned in a related thread), which is now:

int CheckNearlyDone(unsigned axis)
{
    TRIP_COEFF * p = chan[axis].pcoeff;
    if (CS0_StoppingState)
        return 0;
    if (CheckDone(axis) || !p) {
        WaitNextTimeSlice();
        WaitNextTimeSlice();
        if (CheckDone(axis) || !p)
            return 1; // Fully Done
    }
    // Look backwards thru current trip states, before current one.  If any are
    // constant velocity, we must now be decelerating, so nearly done.
    // (Short moves have no CV phase, so these will always full stop).
    while (--p > chan[axis].c)
        if (p->a == 0. && p->b == 0.)
            return -1;  // No t^2 or t^3 coeffs, so must be constant velocity
    return 0;
}


is nice in that there is no need to think of a magic "remaining distance"; the start of deceleration is the optimum point for a nice rounded motion, no matter what speed parameters are set in the configuration.

But if you advise that waiting a few extra time slices is not reliable, then we could change to using distance to go.

Regards,
SJH


On Sat, May 13, 2017 at 11:59 AM, tk@... [DynoMotion] <DynoMotion@yahoogroups.com> wrote:
 

Hi SJH,

I see now there is a flaw where KFLOP on Resume clears CS0_StoppingState
and then immediately commands the motions. So there would be a small
window of time between feedhold clear and no motion. It isn't clear why
my test code doesn't show the issue. But that is the nature of such
issues. Calculating the new Trajectory does involve quite a bit of
calculation and can vary depending on circumstances. I don't see an
elegant solution. I'm still thinking the best solution it to wait for
the destination to be at the target position.

Regards
TK

On 2017-05-12 17:36, Hardy Family hardy.woodland.cypress@gmail. com

[DynoMotion] wrote:
> I tried adding a few WaitNextTimeSlice() calls then do another
> CheckDone(), and it works!
>
> So it looks like I need to be sure, to be sure.
>
> Regards,
> SJH
>
> On Fri, May 12, 2017 at 4:21 PM, Hardy Family
> <hardy.woodland.cypress@gmail. com> wrote:
>
>> It seems like sending a "StopImmediate 1" command from the PC, to
>> resume from a feed hold, is first setting CS0_StoppingState back to
>> zero, but for at least a short time thereafter, CheckDone() returns
>> 1. This causes it to break out of the wait loop.
>>
>> This is the code I am using to debug the wait:
>>
>> void wait_done_dbg(unsigned axis_mask)
>> {
>> unsigned i;
>> unsigned moving = axis_mask;
>> unsigned iam = axis_mask;
>> int css = CS0_StoppingState;
>> double lmdx = ch0->LastMotionDest;
>> double lmdy = ch1->LastMotionDest;
>> double lmdz = ch2->LastMotionDest;
>> int ess = *supe->estop_state;
>> int enab = chan[0].Enable | chan[1].Enable<<1 |
>> chan[2].Enable<<2;
>> int e;
>>
>> printf("WD: Entry: mask=%X, lmd=[%.0f,%.0f,%.0f], ss=%d\n", iam,
>> lmdx, lmdy, lmdz, ess);
>> while (axis_mask) {
>> WaitNextTimeSlice();
>> for (i = 0; i < 5; ++i)
>> if (axis_mask & 1u<<i && CheckDoneFH(i))
>> axis_mask &= ~(1u<<i);
>> if (axis_mask != iam) {
>> printf("WD: axis_mask now %X\n", axis_mask);
>> iam = axis_mask;
>> }
>> if (CS0_StoppingState != css) {
>> printf("WD: stop state now %d\n", CS0_StoppingState);
>> css = CS0_StoppingState;
>> }
>> if (ch0->LastMotionDest != lmdx) {
>> printf("WD: lmd[x] now %.0f\n", ch0->LastMotionDest);
>> lmdx = ch0->LastMotionDest;
>> }
>> if (ch1->LastMotionDest != lmdy) {
>> printf("WD: lmd[y] now %.0f\n", ch1->LastMotionDest);
>> lmdy = ch1->LastMotionDest;
>> }
>> if (ch2->LastMotionDest != lmdz) {
>> printf("WD: lmd[z] now %.0f\n", ch2->LastMotionDest);
>> lmdz = ch2->LastMotionDest;
>> }
>> if (*supe->estop_state != ess) {
>> printf("WD: Estop state now %d\n", *supe->estop_state);
>> ess = *supe->estop_state;
>> }
>> e = chan[0].Enable | chan[1].Enable<<1 | chan[2].Enable<<2;
>> if (e != enab) {
>> printf("WD: Axis enable mask now %X\n", e);
>> enab = e;
>> }
>> }
>> printf("WD: Exit: pos=[%.0f,%.0f,%.0f]\n", ch0->Position,
>> ch1->Position, ch2->Position);
>> if (moving & 1 && fast_fabs(lmdx-ch0->Position) > 100. ||
>> moving & 2 && fast_fabs(lmdy-ch1->Position) > 100. ||
>> moving & 4 && fast_fabs(lmdz-ch2->Position) > 100.)
>> printf("!!!! which ain't even close!\n");
>> }
>>
>> and the console log gets the following for an XY move:
>>
>> + 0 k: WD: Entry: mask=3, lmd=[16500,-94367,11980], ss=0
>> + 0 k: WD: axis_mask now 1
>> + 643 k: WD: stop state now 2
>> + 189 k: WD: stop state now 4
>> + 1804 k: WD: axis_mask now 0
>> + 0 k: WD: stop state now 0
>> + 0 k: WD: Exit: pos=[-56063,-94366,11980]
>> + 0 k: !!!! which ain't even close!
>>
>> (I add the '+ n k:' prefix to print the number of ms since last log
>> print, as seen by the PC.)
>>
>> On the 3rd line, I press feed hold (StopImmediate 0) and the
>> stopping state ends up at 4 with the axis halted. Then at line 5 I
>> release the f/h, and it sees axis_mask==0, which is because
>> CheckDone() returned 1, and at the same time stop state is back to
>> 0. As the next line shows, it didn't end up at the destination.
>>
>> So either the kflop forgot to set CheckDone() to return zero when
>> f/h released but move was not complete, or maybe it takes a few
>> ticks to set it properly.
>>
>> Is there anything else you'd like me to try?
>>
>> BTW, we are still using firmware 433q.
>>
>> Regards,
>> SJH
>>
>> On Wed, May 10, 2017 at 12:31 PM, Hardy Family
>> <hardy.woodland.cypress@gmail. com> wrote:
>>
>> Hi Tom,
>>
>> Yes, it seems to always fail on the 2nd F/H. The *exact* code is
>> rather too complicated to post here, since our build system pulls in
>> code from various places to build the executable for various machine
>> configurations. There is also a supervisor running in another
>> thread, which shouldn't really matter, but it's possible that it is
>> interfering somehow.
>>
>> Let me research this a bit more and I'll get back to you. One thing
>> that might be relevant is that we are actually using the following
>> function instead of the simple 'wait_done' in my original post.
>>
>> int CheckNearlyDone(unsigned axis)
>> {
>> TRIP_COEFF * p = chan[axis].pcoeff;
>> if (CheckDoneFH(axis) || !p)
>> return 1; // Fully Done
>> // Look backwards thru current trip states, before current one.
>> If any are
>> // constant velocity, we must now be decelerating, so nearly
>> done.
>> while (--p > chan[axis].c)
>> if (p->a == 0. && p->b == 0.)
>> return -1; // No t^2 or t^3 coeffs, so must be constant
>> velocity
>> return 0;
>> }
>>
>> so maybe it's this trickiness with checking for pcoeff which is
>> making it break out of the wait prematurely. I'm in the middle of
>> something else at the moment, but probably need to rethink the use
>> of StopState in the above.
>>
>> Regards,
>> SJH
>>
>> On Wed, May 10, 2017 at 10:16 AM, Tom Kerekes tk@...
>> [DynoMotion] <DynoMotion@yahoogroups.com> wrote:
>>
>> Hi SJH,
>>
>> It seems to work ok for one axis for me. How can the routine be
>> returning with stopping state 2 if it only returns when stopping
>> state is 0?
>>
>> Is it failing always on the 2nd feedhold? or only sometimes?
>>
>> Can you post the exact code you are running?
>>
>> This seems to work for me:
>>
>> #include "KMotionDef.h"
>>
>> int CheckDoneFH(int ch)
>> {
>> return CheckDone(ch) && CS0_StoppingState==0;
>> }
>>
>> main()
>> {
>> DefineCoordSystem(0,1,2,-1);
>> MoveRel(0,300000);
>> MoveRel(1,300000);
>> while (!CheckDoneFH(0) && !CheckDoneFH(1)) ;
>> printf("Done\n");
>> DefineCoordSystem(0,1,2,-1);
>> }
>>
>> Regards
>>
>> TK
>>
>> On 5/9/2017 8:24 PM, Hardy Family hardy.woodland.cypress@gmail. com
>> [DynoMotion] wrote:
>>
>> Thanks, that's a big improvement. I added the check for
>> CS0_StoppingState==0 and it works. Unfortunately, it only works for
>> the first feed hold. If I press f/h a second time in the same
>> motion command, it somehow exits the CheckDoneFH loop and yet the
>> stopping state is 2. Maybe there is a moment where CheckDone() is
>> true and stopping state is 0, prior to setting the stopping state
>> non-zero again.
>>
>> Maybe I have a race condition. This move is two axis (X,Y) so the
>> mask is 0x3 in my wait_done() function.
>>
>> Regards,
>> SJH
>>
>> On Tue, May 9, 2017 at 7:42 PM, Tom Kerekes tk@...
>> [DynoMotion] <DynoMotion@yahoogroups.com> wrote:
>>
>> Hi SJH,
>>
>> You might try waiting for CheckDone and not Feedhold like in the
>> code below.
>>
>> Feedhold should make the Axis Done after stopping, but FeedHold will
>> be present. Release of Feedhold should automatically re target the
>> Axes to the original destination.
>>
>> HTH
>>
>> Regards
>>
>> TK
>>
>> #include "KMotionDef.h"
>>
>> //wait for Done and not FeedHold
>> int CheckDoneFH(int ch)
>> {
>> return CheckDone(ch) && CS0_StoppingState==0;
>> }
>>
>> main()
>> {
>> DefineCoordSystem(0,1,2,-1);
>> MoveRel(0,300000);
>> while (!CheckDoneFH(0)) ;
>> printf("Done\n");
>> DefineCoordSystem(0,1,2,-1);
>> }
>>
>> On 5/9/2017 7:26 PM, Hardy Family hardy.woodland.cypress@gmail. com
>> [DynoMotion] wrote:
>>
>> Hi Tom,
>>
>> I have some kflop code to move the axes when operating our tool
>> changer. It calls Move() then checks for completion in a loop using
>> CheckDone(). Unfortunately this doesn't work nicely if the PC
>> application sends a feed hold. If it does, then CheckDone() returns
>> non-zero rather than continuing to return 0 until the f/h is
>> released and the move completes.
>>
>> Am I using this correctly? Ideally, it would be nice to accept f/h
>> during the tool change since it gives the user a chance to load
>> tools etc. if they notice something is wrong. Otherwise, it would
>> be acceptable to somehow inhibit any f/h or overrides. As it is,
>> interrupting any of the move segments generates an error when the
>> code checks that the move really is complete.
>>
>> Just in case it's a snafu on my part, here is the code being used:
>>
>> void wait_done(unsigned axis_mask)
>> {
>> unsigned i;
>> while (axis_mask) {
>> WaitNextTimeSlice();
>> for (i = 0; i < 5; ++i)
>> if (axis_mask & 1u<<i && CheckDone(i))
>> axis_mask &= ~(1u<<i);
>> }
>> }
>>
>> int check_error()
>> {
>> if (*supe->estop_state) {
>> printf("Estop in tool change\n");
>> return 1; // estop is like a cancel
>> }
>> if (!chan[0].Enable || !chan[1].Enable || !chan[2].Enable) {
>> printf("Axis disabled in tool change\n");
>> return 2; // usually following error
>> }
>> if (CS0_StoppingState) {
>> printf("Stopping state %d in tool change\n",
>> CS0_StoppingState);
>> return 3;
>> }
>> return 0;
>> }
>>
>> void move_z(double z)
>> {
>> Move(2, z);
>> wait_done(1u<<2);
>> }
>>
>> int move_z_safe()
>> {
>> // Move to near max Z position (safest for moving to/from work,
>> and manual changes)
>> move_z(SAFE_LEVEL);
>> return check_error();
>> }
>>
>> Regards,
>> SJH
>
>
>
> Links:
> ------
> [1]
> https://groups.yahoo.com/neo/ groups/DynoMotion/ conversations/messages/14742;_ ylc= X3oDMTJyYjlwNHM0BF9TAzk3MzU5Nz E0BGdycElkAzE1ODU4MDAxBGdycHNw SWQDMTcwNjU1NDIwNQRtc2dJZAMxND c0MgRzZWMDZnRyBHNsawNycGx5BHN0 aW1lAzE0OTQ2MzU3OTc-?act= reply&messageNum=14742
> [2]
> https://groups.yahoo.com/neo/ groups/DynoMotion/ conversations/newtopic;_ylc= X3oDMTJmdGRucWhrBF9TAzk3MzU5Nz E0BGdycElkAzE1ODU4MDAxBGdycHNw SWQDMTcwNjU1NDIwNQRzZWMDZnRyBH NsawNudHBjBHN0aW1lAzE0OTQ2MzU3 OTc-
> [3]
> https://groups.yahoo.com/neo/ groups/DynoMotion/ conversations/topics/14714;_ ylc= X3oDMTM3aGZqbTlvBF9TAzk3MzU5Nz E0BGdycElkAzE1ODU4MDAxBGdycHNw SWQDMTcwNjU1NDIwNQRtc2dJZAMxND c0MgRzZWMDZnRyBHNsawN2dHBjBHN0 aW1lAzE0OTQ2MzU3OTcEdHBjSWQDMT Q3MTQ-
> [4] https://yho.com/1wwmgg
> [5]
> https://groups.yahoo.com/neo/ groups/DynoMotion/info;_ylc= X3oDMTJmY3RlaWs0BF9TAzk3MzU5Nz E0BGdycElkAzE1ODU4MDAxBGdycHNw SWQDMTcwNjU1NDIwNQRzZWMDdnRsBH NsawN2Z2hwBHN0aW1lAzE0OTQ2MzU3 OTc-
> [6]
> https://groups.yahoo.com/neo/ groups/DynoMotion/members/all; _ylc= X3oDMTJnZzQxaGRuBF9TAzk3MzU5Nz E0BGdycElkAzE1ODU4MDAxBGdycHNw SWQDMTcwNjU1NDIwNQRzZWMDdnRsBH NsawN2bWJycwRzdGltZQMxNDk0NjM1 Nzk3
> [7]
> https://groups.yahoo.com/neo;_ ylc= X3oDMTJldjNncnQ2BF9TAzk3NDc2NT kwBGdycElkAzE1ODU4MDAxBGdycHNw SWQDMTcwNjU1NDIwNQRzZWMDZnRyBH NsawNnZnAEc3RpbWUDMTQ5NDYzNTc5 Nw--
> [8] https://info.yahoo.com/ privacy/us/yahoo/groups/ details.html
> [9] https://info.yahoo.com/legal/ us/yahoo/utos/terms/


Group: DynoMotion Message: 14755 From: Tom Kerekes Date: 5/15/2017
Subject: Re: Use of feed hold with Move() etc.

Hi SJH,

LastMotionDest should be reliable.  I wouldn't want you to rely on a certain fixed time for the move to begin as it depends on too many things and might possibly change in the future.

Regards

TK


On 5/13/2017 12:59 PM, Hardy Family hardy.woodland.cypress@... [DynoMotion] wrote:
 
I can certainly add the distance-to-go check.  Is the ch0->LastMotionDest field a reliable indicator of the ultimate destination?  If possible, I would like to avoid having to pass the ending coordinates as a parameter to my wait() function, so this would be useful.

Since our tool changer, probing, etc. routines can make a lot of these type of moves, it is a considerable improvement to be able to wait until "nearly there" instead of a complete stop.  The algorithm I coded before (mentioned in a related thread), which is now:

int CheckNearlyDone(unsigned axis)
{
    TRIP_COEFF * p = chan[axis].pcoeff;
    if (CS0_StoppingState)
        return 0;
    if (CheckDone(axis) || !p) {
        WaitNextTimeSlice();
        WaitNextTimeSlice();
        if (CheckDone(axis) || !p)
            return 1; // Fully Done
    }
    // Look backwards thru current trip states, before current one.  If any are
    // constant velocity, we must now be decelerating, so nearly done.
    // (Short moves have no CV phase, so these will always full stop).
    while (--p > chan[axis].c)
        if (p->a == 0. && p->b == 0.)
            return -1;  // No t^2 or t^3 coeffs, so must be constant velocity
    return 0;
}


is nice in that there is no need to think of a magic "remaining distance"; the start of deceleration is the optimum point for a nice rounded motion, no matter what speed parameters are set in the configuration.

But if you advise that waiting a few extra time slices is not reliable, then we could change to using distance to go.

Regards,
SJH


On Sat, May 13, 2017 at 11:59 AM, tk@... [DynoMotion] <DynoMotion@yahoogroups.com> wrote:
 

Hi SJH,

I see now there is a flaw where KFLOP on Resume clears CS0_StoppingState
and then immediately commands the motions. So there would be a small
window of time between feedhold clear and no motion. It isn't clear why
my test code doesn't show the issue. But that is the nature of such
issues. Calculating the new Trajectory does involve quite a bit of
calculation and can vary depending on circumstances. I don't see an
elegant solution. I'm still thinking the best solution it to wait for
the destination to be at the target position.

Regards
TK

On 2017-05-12 17:36, Hardy Family hardy.woodland.cypress@gmail. com

[DynoMotion] wrote:
> I tried adding a few WaitNextTimeSlice() calls then do another
> CheckDone(), and it works!
>
> So it looks like I need to be sure, to be sure.
>
> Regards,
> SJH
>
> On Fri, May 12, 2017 at 4:21 PM, Hardy Family
> <hardy.woodland.cypress@gmail. com> wrote:
>
>> It seems like sending a "StopImmediate 1" command from the PC, to
>> resume from a feed hold, is first setting CS0_StoppingState back to
>> zero, but for at least a short time thereafter, CheckDone() returns
>> 1. This causes it to break out of the wait loop.
>>
>> This is the code I am using to debug the wait:
>>
>> void wait_done_dbg(unsigned axis_mask)
>> {
>> unsigned i;
>> unsigned moving = axis_mask;
>> unsigned iam = axis_mask;
>> int css = CS0_StoppingState;
>> double lmdx = ch0->LastMotionDest;
>> double lmdy = ch1->LastMotionDest;
>> double lmdz = ch2->LastMotionDest;
>> int ess = *supe->estop_state;
>> int enab = chan[0].Enable | chan[1].Enable<<1 |
>> chan[2].Enable<<2;
>> int e;
>>
>> printf("WD: Entry: mask=%X, lmd=[%.0f,%.0f,%.0f], ss=%d\n", iam,
>> lmdx, lmdy, lmdz, ess);
>> while (axis_mask) {
>> WaitNextTimeSlice();
>> for (i = 0; i < 5; ++i)
>> if (axis_mask & 1u<<i && CheckDoneFH(i))
>> axis_mask &= ~(1u<<i);
>> if (axis_mask != iam) {
>> printf("WD: axis_mask now %X\n", axis_mask);
>> iam = axis_mask;
>> }
>> if (CS0_StoppingState != css) {
>> printf("WD: stop state now %d\n", CS0_StoppingState);
>> css = CS0_StoppingState;
>> }
>> if (ch0->LastMotionDest != lmdx) {
>> printf("WD: lmd[x] now %.0f\n", ch0->LastMotionDest);
>> lmdx = ch0->LastMotionDest;
>> }
>> if (ch1->LastMotionDest != lmdy) {
>> printf("WD: lmd[y] now %.0f\n", ch1->LastMotionDest);
>> lmdy = ch1->LastMotionDest;
>> }
>> if (ch2->LastMotionDest != lmdz) {
>> printf("WD: lmd[z] now %.0f\n", ch2->LastMotionDest);
>> lmdz = ch2->LastMotionDest;
>> }
>> if (*supe->estop_state != ess) {
>> printf("WD: Estop state now %d\n", *supe->estop_state);
>> ess = *supe->estop_state;
>> }
>> e = chan[0].Enable | chan[1].Enable<<1 | chan[2].Enable<<2;
>> if (e != enab) {
>> printf("WD: Axis enable mask now %X\n", e);
>> enab = e;
>> }
>> }
>> printf("WD: Exit: pos=[%.0f,%.0f,%.0f]\n", ch0->Position,
>> ch1->Position, ch2->Position);
>> if (moving & 1 && fast_fabs(lmdx-ch0->Position) > 100. ||
>> moving & 2 && fast_fabs(lmdy-ch1->Position) > 100. ||
>> moving & 4 && fast_fabs(lmdz-ch2->Position) > 100.)
>> printf("!!!! which ain't even close!\n");
>> }
>>
>> and the console log gets the following for an XY move:
>>
>> + 0 k: WD: Entry: mask=3, lmd=[16500,-94367,11980], ss=0
>> + 0 k: WD: axis_mask now 1
>> + 643 k: WD: stop state now 2
>> + 189 k: WD: stop state now 4
>> + 1804 k: WD: axis_mask now 0
>> + 0 k: WD: stop state now 0
>> + 0 k: WD: Exit: pos=[-56063,-94366,11980]
>> + 0 k: !!!! which ain't even close!
>>
>> (I add the '+ n k:' prefix to print the number of ms since last log
>> print, as seen by the PC.)
>>
>> On the 3rd line, I press feed hold (StopImmediate 0) and the
>> stopping state ends up at 4 with the axis halted. Then at line 5 I
>> release the f/h, and it sees axis_mask==0, which is because
>> CheckDone() returned 1, and at the same time stop state is back to
>> 0. As the next line shows, it didn't end up at the destination.
>>
>> So either the kflop forgot to set CheckDone() to return zero when
>> f/h released but move was not complete, or maybe it takes a few
>> ticks to set it properly.
>>
>> Is there anything else you'd like me to try?
>>
>> BTW, we are still using firmware 433q.
>>
>> Regards,
>> SJH
>>
>> On Wed, May 10, 2017 at 12:31 PM, Hardy Family
>> <hardy.woodland.cypress@gmail. com> wrote:
>>
>> Hi Tom,
>>
>> Yes, it seems to always fail on the 2nd F/H. The *exact* code is
>> rather too complicated to post here, since our build system pulls in
>> code from various places to build the executable for various machine
>> configurations. There is also a supervisor running in another
>> thread, which shouldn't really matter, but it's possible that it is
>> interfering somehow.
>>
>> Let me research this a bit more and I'll get back to you. One thing
>> that might be relevant is that we are actually using the following
>> function instead of the simple 'wait_done' in my original post.
>>
>> int CheckNearlyDone(unsigned axis)
>> {
>> TRIP_COEFF * p = chan[axis].pcoeff;
>> if (CheckDoneFH(axis) || !p)
>> return 1; // Fully Done
>> // Look backwards thru current trip states, before current one.
>> If any are
>> // constant velocity, we must now be decelerating, so nearly
>> done.
>> while (--p > chan[axis].c)
>> if (p->a == 0. && p->b == 0.)
>> return -1; // No t^2 or t^3 coeffs, so must be constant
>> velocity
>> return 0;
>> }
>>
>> so maybe it's this trickiness with checking for pcoeff which is
>> making it break out of the wait prematurely. I'm in the middle of
>> something else at the moment, but probably need to rethink the use
>> of StopState in the above.
>>
>> Regards,
>> SJH
>>
>> On Wed, May 10, 2017 at 10:16 AM, Tom Kerekes tk@...
>> [DynoMotion] <DynoMotion@yahoogroups.com> wrote:
>>
>> Hi SJH,
>>
>> It seems to work ok for one axis for me. How can the routine be
>> returning with stopping state 2 if it only returns when stopping
>> state is 0?
>>
>> Is it failing always on the 2nd feedhold? or only sometimes?
>>
>> Can you post the exact code you are running?
>>
>> This seems to work for me:
>>
>> #include "KMotionDef.h"
>>
>> int CheckDoneFH(int ch)
>> {
>> return CheckDone(ch) && CS0_StoppingState==0;
>> }
>>
>> main()
>> {
>> DefineCoordSystem(0,1,2,-1);
>> MoveRel(0,300000);
>> MoveRel(1,300000);
>> while (!CheckDoneFH(0) && !CheckDoneFH(1)) ;
>> printf("Done\n");
>> DefineCoordSystem(0,1,2,-1);
>> }
>>
>> Regards
>>
>> TK
>>
>> On 5/9/2017 8:24 PM, Hardy Family hardy.woodland.cypress@gmail. com
>> [DynoMotion] wrote:
>>
>> Thanks, that's a big improvement. I added the check for
>> CS0_StoppingState==0 and it works. Unfortunately, it only works for
>> the first feed hold. If I press f/h a second time in the same
>> motion command, it somehow exits the CheckDoneFH loop and yet the
>> stopping state is 2. Maybe there is a moment where CheckDone() is
>> true and stopping state is 0, prior to setting the stopping state
>> non-zero again.
>>
>> Maybe I have a race condition. This move is two axis (X,Y) so the
>> mask is 0x3 in my wait_done() function.
>>
>> Regards,
>> SJH
>>
>> On Tue, May 9, 2017 at 7:42 PM, Tom Kerekes tk@...
>> [DynoMotion] <DynoMotion@yahoogroups.com> wrote:
>>
>> Hi SJH,
>>
>> You might try waiting for CheckDone and not Feedhold like in the
>> code below.
>>
>> Feedhold should make the Axis Done after stopping, but FeedHold will
>> be present. Release of Feedhold should automatically re target the
>> Axes to the original destination.
>>
>> HTH
>>
>> Regards
>>
>> TK
>>
>> #include "KMotionDef.h"
>>
>> //wait for Done and not FeedHold
>> int CheckDoneFH(int ch)
>> {
>> return CheckDone(ch) && CS0_StoppingState==0;
>> }
>>
>> main()
>> {
>> DefineCoordSystem(0,1,2,-1);
>> MoveRel(0,300000);
>> while (!CheckDoneFH(0)) ;
>> printf("Done\n");
>> DefineCoordSystem(0,1,2,-1);
>> }
>>
>> On 5/9/2017 7:26 PM, Hardy Family hardy.woodland.cypress@gmail. com
>> [DynoMotion] wrote:
>>
>> Hi Tom,
>>
>> I have some kflop code to move the axes when operating our tool
>> changer. It calls Move() then checks for completion in a loop using
>> CheckDone(). Unfortunately this doesn't work nicely if the PC
>> application sends a feed hold. If it does, then CheckDone() returns
>> non-zero rather than continuing to return 0 until the f/h is
>> released and the move completes.
>>
>> Am I using this correctly? Ideally, it would be nice to accept f/h
>> during the tool change since it gives the user a chance to load
>> tools etc. if they notice something is wrong. Otherwise, it would
>> be acceptable to somehow inhibit any f/h or overrides. As it is,
>> interrupting any of the move segments generates an error when the
>> code checks that the move really is complete.
>>
>> Just in case it's a snafu on my part, here is the code being used:
>>
>> void wait_done(unsigned axis_mask)
>> {
>> unsigned i;
>> while (axis_mask) {
>> WaitNextTimeSlice();
>> for (i = 0; i < 5; ++i)
>> if (axis_mask & 1u<<i && CheckDone(i))
>> axis_mask &= ~(1u<<i);
>> }
>> }
>>
>> int check_error()
>> {
>> if (*supe->estop_state) {
>> printf("Estop in tool change\n");
>> return 1; // estop is like a cancel
>> }
>> if (!chan[0].Enable || !chan[1].Enable || !chan[2].Enable) {
>> printf("Axis disabled in tool change\n");
>> return 2; // usually following error
>> }
>> if (CS0_StoppingState) {
>> printf("Stopping state %d in tool change\n",
>> CS0_StoppingState);
>> return 3;
>> }
>> return 0;
>> }
>>
>> void move_z(double z)
>> {
>> Move(2, z);
>> wait_done(1u<<2);
>> }
>>
>> int move_z_safe()
>> {
>> // Move to near max Z position (safest for moving to/from work,
>> and manual changes)
>> move_z(SAFE_LEVEL);
>> return check_error();
>> }
>>
>> Regards,
>> SJH
>
>
>
> Links:
> ------
> [1]
> https://groups.yahoo.com/neo/ groups/DynoMotion/ conversations/messages/14742;_ ylc= X3oDMTJyYjlwNHM0BF9TAzk3MzU5Nz E0BGdycElkAzE1ODU4MDAxBGdycHNw SWQDMTcwNjU1NDIwNQRtc2dJZAMxND c0MgRzZWMDZnRyBHNsawNycGx5BHN0 aW1lAzE0OTQ2MzU3OTc-?act= reply&messageNum=14742
> [2]
> https://groups.yahoo.com/neo/ groups/DynoMotion/ conversations/newtopic;_ylc= X3oDMTJmdGRucWhrBF9TAzk3MzU5Nz E0BGdycElkAzE1ODU4MDAxBGdycHNw SWQDMTcwNjU1NDIwNQRzZWMDZnRyBH NsawNudHBjBHN0aW1lAzE0OTQ2MzU3 OTc-
> [3]
> https://groups.yahoo.com/neo/ groups/DynoMotion/ conversations/topics/14714;_ ylc= X3oDMTM3aGZqbTlvBF9TAzk3MzU5Nz E0BGdycElkAzE1ODU4MDAxBGdycHNw SWQDMTcwNjU1NDIwNQRtc2dJZAMxND c0MgRzZWMDZnRyBHNsawN2dHBjBHN0 aW1lAzE0OTQ2MzU3OTcEdHBjSWQDMT Q3MTQ-
> [4] https://yho.com/1wwmgg
> [5]
> https://groups.yahoo.com/neo/ groups/DynoMotion/info;_ylc= X3oDMTJmY3RlaWs0BF9TAzk3MzU5Nz E0BGdycElkAzE1ODU4MDAxBGdycHNw SWQDMTcwNjU1NDIwNQRzZWMDdnRsBH NsawN2Z2hwBHN0aW1lAzE0OTQ2MzU3 OTc-
> [6]
> https://groups.yahoo.com/neo/ groups/DynoMotion/members/all; _ylc= X3oDMTJnZzQxaGRuBF9TAzk3MzU5Nz E0BGdycElkAzE1ODU4MDAxBGdycHNw SWQDMTcwNjU1NDIwNQRzZWMDdnRsBH NsawN2bWJycwRzdGltZQMxNDk0NjM1 Nzk3
> [7]
> https://groups.yahoo.com/neo;_ ylc= X3oDMTJldjNncnQ2BF9TAzk3NDc2NT kwBGdycElkAzE1ODU4MDAxBGdycHNw SWQDMTcwNjU1NDIwNQRzZWMDZnRyBH NsawNnZnAEc3RpbWUDMTQ5NDYzNTc5 Nw--
> [8] https://info.yahoo.com/ privacy/us/yahoo/groups/ details.html
> [9] https://info.yahoo.com/legal/ us/yahoo/utos/terms/